局域网当前已经具备公网 IPv6,但运营商下发的 IPv6 前缀可能发生变化。
为了给局域网设备提供一组稳定的 IPv6 地址,用于本地访问和防火墙规则配置,计划在小米路由器上增加一个固定的 ULA(Unique Local Address)前缀:
fd00:1:1::/48目标是让局域网设备同时具备:
公网 GUA IPv6 → 用于访问 Internet
fd00:1:1::/48 → 用于稳定的局域网地址主路由为小米路由器,系统基于 OpenWrt 修改,因此在正式修改前先确认其 netifd 和 UCI 是否支持标准 OpenWrt 的 ULA 配置。
#1. 检查现有 IPv6 配置
首先查看是否已经配置 ULA:
uci get network.globals.ula_prefix结果:
uci: Entry not found说明当前没有设置 ULA。
检查 LAN IPv6 前缀分配:
uci show network.lan | grep -E 'ip6assign|ip6class'结果:
network.lan.ip6assign='64'说明 LAN 已配置 /64 IPv6 子网分配。
检查 RA 和 DHCPv6:
uci show dhcp.lan | grep -E 'ra=|dhcpv6='结果:
dhcp.lan.dhcpv6='server'
dhcp.lan.ra='server'因此主路由已经负责向 LAN 发布 IPv6 RA 和 DHCPv6。
#2. 检查 globals 配置
执行:
uci show network | grep '=globals'没有输出。
随后查看完整网络配置:
cat /etc/config/network其中 LAN 主要配置为:
config interface 'lan'
option proto 'static'
option ip6assign '64'
option ipaddr '*.*.*.1'WAN6 使用 DHCPv6:
config interface 'wan_6'
option proto 'dhcpv6'
option reqaddress 'try'
option reqprefix 'auto'说明整体仍沿用了 OpenWrt 标准的 IPv6 prefix delegation 结构。
#3. 测试 UCI 是否接受 ULA 配置
先不提交配置,仅在 UCI staging 状态下增加:
uci set network.globals=globals
uci set network.globals.ula_prefix='fd00:1:1::/48'可以使用如下命令生成前缀:
python3 - <<'PY'
import secrets
x = secrets.token_hex(5)
print(f"fd{x[:2]}:{x[2:6]}:{x[6:]}::/48")
PY检查待提交修改:
uci changes network得到:
network.globals='globals'
network.globals.ula_prefix='fd00:1:1::/48'继续确认:
uci show network.globals结果:
network.globals=globals
network.globals.ula_prefix='fd00:1:1::/48'说明 UCI 可以正常接受该配置。
#4. 确认 netifd 是否支持 ULA
首先尝试搜索相关脚本:
grep -R "ula_prefix\|ip6assign" /lib/netifd /etc/init.d /usr/sbin 2>/dev/null | head -50没有结果。
由于相关逻辑可能直接编译在 netifd 中,因此继续检查二进制:
which netifd结果:
/sbin/netifd检查内部字符串:
strings "$(which netifd)" | grep -E 'ula_prefix|ip6assign|ip6hint'得到:
ip6assign
ip6hint
You have delegated IPv6-prefixes but haven't assigned them to any interface. Did you forget to set option ip6assign on your lan-interfaces?
ula_prefix这证明该小米固件中的 netifd 包含:
ula_prefix
ip6assign
ip6hint因此基本可以确认仍支持 OpenWrt 标准的 ULA 分配机制。
#5. 检查配置文件是否可写
小米系统根文件系统为只读 SquashFS:
mount | grep -E 'overlay| / '结果:
/dev/root on / type squashfs (ro,noatime)但进一步检查:
test -w /etc/config/network && echo writable || echo readonly结果:
writable同时:
ls -l /etc/config/network显示:
-rwxr-xr-x 1 root root ... /etc/config/network因此虽然根文件系统本身是只读 SquashFS,但 /etc/config/network 实际可以持久写入。
#6. 正式提交 ULA 配置
确认配置后执行:
uci commit network检查配置文件:
grep -A3 "config globals" /etc/config/network得到:
config globals 'globals'
option ula_prefix 'fd00:1:1::/48'ULA 已正式写入配置。
#7. 重新加载网络
最初尝试直接查询:
ubus call network.interface.lan status | grep -A10 -B2 'fd00'此时还没有看到 ULA,因为 netifd 尚未重新加载配置。
随后执行:
/etc/init.d/network reload需要特别记录:
在这台小米路由器上执行
network reload会造成整个网络短暂中断。
因此后续不建议在远程环境中随意执行该命令。
如果再次需要调整主路由网络配置,应提前确保存在本地管理或其他恢复手段。
#8. 验证 ULA 是否下发成功
网络恢复后,在 Debian 旁路由执行:
ip -6 addr show可以看到 Debian 已经获得:
fd00:1:1:...开头的 IPv6 地址。
这说明配置链路已经成功:
小米主路由
fd00:1:1::/48
│
│ netifd 分配 /64
↓
LAN
│
│ IPv6 RA
↓
Debian / 其他局域网设备
fd00:1:1:xxxx:....../64设备同时仍可保留运营商提供的公网 IPv6 地址。
#最终配置
主路由 /etc/config/network 中新增:
config globals 'globals'
option ula_prefix 'fd00:1:1::/48'LAN 原有:
option ip6assign '64'DHCP/RA 原有:
dhcp.lan.dhcpv6='server'
dhcp.lan.ra='server'最终 LAN 设备可以同时拥有:
公网 IPv6 动态,随运营商前缀变化
fd00:1:1:... 稳定,用于内部访问
fe80::... IPv6 link-local
fd7a:... Tailscale IPv6(如果安装 Tailscale)#用途
稳定 ULA 可以用于局域网访问控制。例如 Debian 旁路由的 IPv6 INPUT 防火墙可以允许整个家庭 ULA:
ip6tables -A INPUT -i eth0 -s fd00:1:1::/48 -j ACCEPT同时:
IPv6 INPUT 默认 DROP
IPv6 FORWARD ACCEPT这样可以实现:
LAN ULA → Debian 允许
Tailscale → Debian 允许
公网 IPv6 → Debian 默认拒绝
Debian → Internet 允许
Debian 转发 LAN 流量 允许#注意事项
fd00:1:1::/48是人为规划的 ULA 前缀,而不是随机生成的 RFC 4193 Global ID。家庭内部使用没有技术问题,但如果未来与其他采用相同 ULA 的网络互联,理论上可能产生地址冲突。这台小米固件虽然保留标准 OpenWrt 的
netifd、UCI、ip6assign和ula_prefix支持,但网络管理层仍有小米自己的修改。/etc/init.d/network reload在实际测试中导致整个网络中断,因此不应把它视为无影响的 reload 操作。ULA 不替代公网 IPv6。正常情况下客户端同时保留 GUA 和 ULA:公网通信继续使用 GUA,ULA 主要用于本地稳定寻址。
不需要 NAT66。ULA 的用途是局域网内部通信,而不是通过 NAT 转换后访问公网。